package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.CustomBottom;
import com.myk.game.gobangchess.DataManager;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsMultiViewRoom;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.awt.*;
import java.util.List;
import java.util.*;

/**
 * 对称消消乐改动：
 * 1.对称棋形标黄色并不显眼，改一种颜色（颜色随便抄7b或者幽灵棋的）
 * 2.双胜/双败分数改为60/10
 * 3.电脑落子规则，改为每回合电脑固定落4子，具体算法需求如下：
 * 权重：完全不与任何同色棋子相邻格子的落子权重为15，相邻落子权重为1
 * 4.一方剩余空位（小点）少于15个时，出现一个黄色的字体警告，提醒X方剩余空位较少，请尽快得分
 * 5.黄色警告出现后，下一回合变为橙色警告，再下回合变成红色警告，当红色警告出现时，若该回合再无得分，则立刻结束游戏
 * 6.移除现有的随机落子数提示
 * 7.更新游戏文本：
 * 《对称消消乐》
 * 作者：日出
 * <p>
 * 【行棋过程】
 * 每回合：先由电脑随机落4子，然后由玩家任意移动1子。
 * 只要形成六子以上、独立完整的轴对称棋形，系统会自动消除并得分。
 * 【胜负判断】
 * 当红色警告出现时，若该回合无得分，则立刻结束游戏
 * 如果双方都高于60分，则双胜。
 * 如果双方都低于10分，则双败。
 * 11-59分之间，分高胜，同分和。
 * 【补充说明】
 * 1）相邻、相连，包含纵横斜方向。
 * 2）电脑随机落4子：更大概率落在“跟同色棋子不相邻”的位置。
 * 3）当电脑判断剩余空位较少时，就会发起「黄色警告」；「黄色警告」出现后，接着会变成「橙色警告」「红色警告」，得分时，取消该警告
 */
public class SoloShapeRoom extends AbsMultiViewRoom {


    private final int BOTH_FAIL = 10;//双败数量
    private final int BOTH_WIN = 60;//双赢数量
    private final int weight1 = 10;
//    private final int weight2 = 1;
    private static final String PITCH_BG_COLOR = "#FF186597";//对称棋型背景颜色
    private static final String YELLOW_COLOR = "#FFFFFF00";
    private static final String ORANGE_COLOR = "#FFFFA500";
    private static final String RED_COLOR = "#FFFF0000";
    private boolean isTaskScheduled;

    private ActionState actionState; //当前行动状态
    private final int maxScore = 4; //获胜需要的最大分数
    private Point tempPoint; //切换到移子挤子状态时记录的临时坐标
    private GroundSign fallTip; //最新落子提示信息
    //双方的警告 0为无警告，1为黄色警告，2为橙色警告，3为红色警告
    private int blackWarnning = 0;
    private int whtieWarnning = 0;//
    //    blackWarnning = 0;
    //    whtieWarnning = 0;
    private Timer buttonTimer;

    private TimerTask task_btn = new TimerTask() {
        @Override
        public void run() {
            // 这里定义需要定时执行的任务逻辑
            player_black.registerCustomBottom(cb_endGame);
            player_white.registerCustomBottom(cb_endGame);
            System.out.println("定时任务被执行了");

            isTaskScheduled = false;

        }
    };

    CustomBottom cb_endGame = new CustomBottom(this, "认赢", (player) -> {

        player_black.clearCustomBottom();
        player_white.clearCustomBottom();
        player_black.dispatchCustomBottom();
        player_white.dispatchCustomBottom();
        changeState(ActionState.BLACK_AND_WHITE_WIN);
    });

    private int autoPutNum = 4;//自动放置棋子数量
    private boolean hadEnd = false;
    private AroundSign fallTipByAuto;
    private LineSign arrowTip; //移动箭头提示信息s
    private List<ChessInfo> pieces; //棋盘上的棋子信息集合
    private List<ChessInfo> symmetryPieces; //形成了对称的棋子信息集合

    public SoloShapeRoom(String roomName) {
        super(roomName, "\t\t《形棋》娱乐玩法", "对称消消乐", BoardStyleData.getGoBangStyle(15, 15), true, true);
    }

    @Override
    public String getRuleText() {
        return "对称消消乐\n" +
                "\n" +
                "【行棋过程】\n" +
                "每回合：先由电脑随机落4子，然后由玩家任意移动1子。\n" +
                "只要形成六子以上、独立完整的轴对称棋形，系统会自动消除并得分。\n" +
                "【胜负判断】\n" +
                "当红色警告出现时，若该回合无得分，则立刻结束游戏\n" +
                "如果双方都高于60分，则双胜。\n" +
                "如果双方都低于10分，则双败。\n" +
                "11-59分之间，分高胜，同分和。\n" +
                "【补充说明】\n" +
                "1）相邻、相连，包含纵横斜方向。\n" +
                "2）电脑随机落4子：更大概率落在“跟同色棋子不相邻”的位置。\n" +
                "3）当电脑判断剩余空位较少时，就会发起「黄色警告」；「黄色警告」出现后，接着会变成「橙色警告」「红色警告」，得分时，取消该警告";
    }

    @Override
    public void resetGrids() {
        step = 0;
        blackScore = 0;
        whiteScore = 0;
        gameTip = "-1";
        actionState = null;
        tempPoint = null;
        fallTip = null;
        arrowTip = null;
        pieces = new ArrayList<>();
        blackWarnning = 0;
        whtieWarnning = 0;
        symmetryPieces = new ArrayList<>();
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        hadEnd = false;
        cur = 0;
        if (isTaskScheduled)
            buttonTimer.cancel();

    }

    @Override
    protected void doStart() {
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids();
        changeState(ActionState.WAIT_FALL_BLACK);
        noticeBlackMove();
        hadEnd = false;
        //whiteScore+=0.5;
        preHistory(); //准备记录日志
        buttonTimer = new Timer();
        task_btn = new TimerTask() {
            @Override
            public void run() {
                // 这里定义需要定时执行的任务逻辑
                player_black.registerCustomBottom(cb_endGame);
                player_white.registerCustomBottom(cb_endGame);
                System.out.println("定时任务被执行了");

                isTaskScheduled = false;

            }
        };
        buttonTimer.schedule(task_btn, 40 * 60 * 1000);
        isTaskScheduled = true;
    }

    @Override
    public String getGameInfo(int view) {
        curGrids = GridsUtils.copyGrids(originGrids);
        signList.clear();
        //绘制棋子
        if (pieces != null && pieces.size() > 0) {
            for (ChessInfo piece : pieces) {
                curGrids[piece.row][piece.col] = piece.isBlack ? 1 : 2;
            }
        }

        //绘制提示标记
        if (fallTip != null) {
            signList.add(fallTip);
            if (fallTipByAuto != null && !hadEnd) {
                signList.add(fallTipByAuto);
            }
            //绘制白子可被挤到的位置
            if (checkState(ActionState.PUSH_AWAY_WHITE)) {
                int pRow = tempPoint.y;
                int pCol = tempPoint.x;
                int maxRow = curGrids.length - 1;
                int maxCol = curGrids[0].length - 1;
                signList.add(new BadgeSign(getIndex(tempPoint.y, tempPoint.x), "p", 2, "#00FFFFFF", ColorCost.DETAINED_BADGE_BLACK));
                List<Integer> signIds = new ArrayList<>();
                if (pRow > 0 && pCol > 0 && curGrids[pRow - 1][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol - 1));
                }
                if (pRow > 0 && curGrids[pRow - 1][pCol] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol));
                }
                if (pRow > 0 && pCol < maxCol && curGrids[pRow - 1][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol + 1));
                }
                if (pCol > 0 && curGrids[pRow][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow, pCol - 1));
                }
                if (pCol < maxCol && curGrids[pRow][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow, pCol + 1));
                }
                if (pRow < maxRow && pCol > 0 && curGrids[pRow + 1][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol - 1));
                }
                if (pRow < maxRow && curGrids[pRow + 1][pCol] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol));
                }
                if (pRow < maxRow && pCol < maxCol && curGrids[pRow + 1][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol + 1));
                }
                signList.add(new AroundSign(new ArrayList<>(signIds), "#4411EE11", "#FF00FF00", 1.0f));
            }
            //绘制黑子可被挤到的位置
            else if (checkState(ActionState.PUSH_AWAY_BLACK)) {
                int pRow = tempPoint.y;
                int pCol = tempPoint.x;
                int maxRow = curGrids.length - 1;
                int maxCol = curGrids[0].length - 1;
                signList.add(new BadgeSign(getIndex(tempPoint.y, tempPoint.x), "p", 2, "#00FFFFFF", ColorCost.DETAINED_BADGE_WHITE));
                List<Integer> signIds = new ArrayList<>();
                if (pRow > 0 && pCol > 0 && curGrids[pRow - 1][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol - 1));
                }
                if (pRow > 0 && curGrids[pRow - 1][pCol] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol));
                }
                if (pRow > 0 && pCol < maxCol && curGrids[pRow - 1][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow - 1, pCol + 1));
                }
                if (pCol > 0 && curGrids[pRow][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow, pCol - 1));
                }
                if (pCol < maxCol && curGrids[pRow][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow, pCol + 1));
                }
                if (pRow < maxRow && pCol > 0 && curGrids[pRow + 1][pCol - 1] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol - 1));
                }
                if (pRow < maxRow && curGrids[pRow + 1][pCol] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol));
                }
                if (pRow < maxRow && pCol < maxCol && curGrids[pRow + 1][pCol + 1] == 0) {
                    signIds.add(getIndex(pRow + 1, pCol + 1));
                }
                signList.add(new AroundSign(new ArrayList<>(signIds), "#4411EE11", "#FF00FF00", 1.0f));
            }
        }
        //绘制移动提示
        if (arrowTip != null) {
            signList.add(arrowTip);
        }

        //绘制成型范围标记
        if (symmetryPieces != null && symmetryPieces.size() > 0) {
            List<Integer> signIds = new ArrayList<>();
            for (ChessInfo symmetryPiece : symmetryPieces) {
                signIds.add(getIndex(symmetryPiece.row, symmetryPiece.col));
            }
            signList.add(new AroundSign(new ArrayList<>(signIds), PITCH_BG_COLOR, "#00FFDD00", 1.2f));
        }

        if (!hadEnd) {

//            List<Integer> signIds = new ArrayList<>();
            //绘制电脑可落子范围
            if (view == 1) {
                for (int i = 0; i < curGrids.length; i++) {
                    for (int j = 0; j < curGrids[0].length; j++) {
                        if (isKingPosition(curGrids, i, j, 1)) {
//                        signIds.add(getIndex(i,j));
                            signList.add(new TextSign(getIndex(i, j), "·", "#FF000000"));
                        }
                    }
                }
            } else if (view == 2) {
                for (int i = 0; i < curGrids.length; i++) {
                    for (int j = 0; j < curGrids[0].length; j++) {
                        if (isKingPosition(curGrids, i, j, 2)) {
//                        signIds.add(getIndex(i,j));
                            signList.add(new TextSign(getIndex(i, j), "·", "#FFFFFFFF"));
                        }
                    }
                }
            } else {
                for (int i = 0; i < curGrids.length; i++) {
                    for (int j = 0; j < curGrids[0].length; j++) {
                        if (isKingPosition(curGrids, i, j, cur == 1 ? 1 : 2)) {
//                        signIds.add(getIndex(i,j));
                            if (cur == 1) {
                                signList.add(new TextSign(getIndex(i, j), "·", "#FF000000"));
                            } else {
                                signList.add(new TextSign(getIndex(i, j), "·", "#FFFFFFFF"));
                            }
                        }
                    }
                }
            }
//            signList.add(new AroundSign(new ArrayList<>(signIds), "#FFFF0000", "#00000000", 1.2f));
        }

        //绘制下次会落子数
        //●
//        int blackCount = GridsUtils.getDataCount(curGrids, 1);
//        int whiteCount = GridsUtils.getDataCount(curGrids, 2);
//        int bPutNum;
//        int wPutNum;
//        if (whiteCount < 16) {
//            bPutNum = 4;
//        } else if (whiteCount < 31) {
//            bPutNum = 3;
//        } else {
//            bPutNum = 2;
//        }
//
//        if (blackCount < 16) {
//            wPutNum = 4;
//        } else if (blackCount < 31) {
//            wPutNum = 3;
//        } else {
//            wPutNum = 2;
//        }

        float bGClipX = (0 + 1f) / curGrids[0].length;//1
        float wBClipX = (curGrids[0].length - 1f) / curGrids[0].length;//1
        float aClipY = (curGrids.length + 0.2f) / curGrids.length;
//        StringBuilder bGStr = new StringBuilder();
//        for (int i = 0; i < wPutNum; i++) {
//            bGStr.append("●");
//        }
        if (blackWarnning != 0) {
            signList.add(new TitleSign(bGClipX, aClipY, 0, "警告", blackWarnning == 1 ? YELLOW_COLOR : (blackWarnning == 2 ? ORANGE_COLOR : RED_COLOR), 0.4f));
        }
//        StringBuilder bBStr = new StringBuilder();
//        for (int i = 0; i < bPutNum; i++) {
//            bBStr.append("●");
//        }
        if (whtieWarnning != 0) {
            signList.add(new TitleSign(wBClipX, aClipY, 0, "警告", whtieWarnning == 1 ? YELLOW_COLOR : (whtieWarnning == 2 ? ORANGE_COLOR : RED_COLOR), 0.4f));
        }
//        signList.add(new TitleSign(wBClipX, aClipY, 0, bBStr.toString(), "#FFFFFFFF", 0.4f));


//        long curTime = System.currentTimeMillis();
//        if (curTime - playingStartTime > 40 * 60 * 1000){
//
//        }
        return super.getGameInfo();
    }

    @Override
    public void doRule(int row, int col, int value) {
        processFallAction(col, row);
    }

    //处理落子行为
    private void processFallAction(int pCol, int pRow) {
        //根据坐标获取该位置的信息，为null就是空位置，不为空就是已有棋子了
        ChessInfo chessInfo = getChessByPoint(pCol, pRow);
        arrowTip = null; //默认清除箭头提示
        //等待黑棋落子
        if (checkState(ActionState.WAIT_FALL_BLACK)) {
            //落在空白处
            if (chessInfo == null) {
                return;
//                fallPiece(true, pCol, pRow); //落下黑棋子
//                setFallTip(pCol, pRow); //添加落子提示
//                //黑棋成型了
//                if (checkSymmetryShape(true)) {
//                    changeState(ActionState.REMOVE_SHAPED_BLACK);//切换到黑棋快捷提子状态
//                }
//                //黑棋没成型
//                else {
//                    changeState(ActionState.WAIT_FALL_WHITE);//自动交换白棋行棋
//                }
            }
            //落在有子处
            else {
                setFallTip(pCol, pRow); //添加落子提示
                setTempPoint(pCol, pRow); //记录落子位置
                //落子已有的黑棋处，可以移动黑棋
                if (chessInfo.isBlack) {
                    pieces.remove(chessInfo); //移除该棋子
                    changeState(ActionState.THEN_MOVE_BLACK); //切换到移动黑子的状态
                }
                //落在已有的白棋处
                else {
                    return;
//                    if (checkHasQi(pCol, pRow)) {
//                        chessInfo.isBlack = true; //白棋变为黑棋
//                        changeState(ActionState.PUSH_AWAY_WHITE); //切换到挤走白子的状态
//                    }
                }
            }
        }
        //等待白棋落子
        else if (checkState(ActionState.WAIT_FALL_WHITE)) {
            //落在空白处
            if (chessInfo == null) {
                return;
//                fallPiece(false, pCol, pRow); //落下白棋子
//                setFallTip(pCol, pRow); //添加落子提示
//                //白棋成型了
//                if (checkSymmetryShape(false)) {
//                    changeState(ActionState.REMOVE_SHAPED_WHITE);//切换到白棋快捷提子状态
//                }
//                //白棋没成型
//                else {
//                    changeState(ActionState.WAIT_FALL_BLACK);//自动交换黑棋行棋
//                }
            } else {
                setFallTip(pCol, pRow); //添加落子提示
                setTempPoint(pCol, pRow); //记录落子位置
                //落子已有的白棋处，可以移动白棋
                if (!chessInfo.isBlack) {
                    pieces.remove(chessInfo); //移除该棋子
                    changeState(ActionState.THEN_MOVE_WHITE); //切换到移动白子的状态
                }
                //落在已有的黑棋处
                else {
                    return;
//                    if (checkHasQi(pCol, pRow)) {
//                        chessInfo.isBlack = false; //黑棋变为白棋
//                        changeState(ActionState.PUSH_AWAY_BLACK); //切换到挤走黑子的状态
//                    }
                }
            }
        }
        //等待黑方移动黑棋
        else if (checkState(ActionState.THEN_MOVE_BLACK)) {
            //移动到空白位置
            if (chessInfo == null) {
                //移动到不同位置
                if (tempPoint.x != pCol || tempPoint.y != pRow) {
                    fallPiece(true, pCol, pRow); //移动黑棋到此处
                    setFallTip(tempPoint.x, tempPoint.y); //添加上一步落子提示
                    setArrowTip(pCol, pRow); //添加箭头提示
                    //黑棋成型了
                    if (checkSymmetryShape(true)) {
                        changeState(ActionState.REMOVE_SHAPED_BLACK);//切换到黑棋快捷提子状态222222222222222222
                        //gameTip = "「请点击对称图消除得分」";
//                        iGameUI.toast("「请点击对称图消除得分」"); //提示用户正确的操作
//                        int size = symmetryPieces.size();
//                        pieces.removeAll(symmetryPieces); //批量提子
//                        int score = size - 5; //计算得分
//                        blackScore += score; //加分
//                if (blackScore >= maxScore) {
//                    changeState(ActionState.BLACK_WIN); //黑棋获胜
//                }
//                else {
//                        changeState(ActionState.WAIT_FALL_WHITE); //提子后走白棋
                    }
                    //黑棋没成型
                    else {
                        changeState(ActionState.WAIT_FALL_WHITE);//自动交换白棋行棋
                    }
                }
                //移动到原位置
                else {
                    //iGameUI.toast("不能移动到这个位置"); //提示用户不能这么做
                    setFallTip(tempPoint.x, tempPoint.y); //还原聚焦提示
                }
            }
            //移动的位置有棋
            else {
                //iGameUI.toast("不能移动到这个位置"); //提示用户不能这么做
                setFallTip(tempPoint.x, tempPoint.y); //还原落子提示
            }
        }
        //等待白方移动白棋
        else if (checkState(ActionState.THEN_MOVE_WHITE)) {
            //移动到空白位置
            if (chessInfo == null) {
                //移动到不同位置
                if (tempPoint.x != pCol || tempPoint.y != pRow) {
                    fallPiece(false, pCol, pRow); //移动白棋到此处
                    setFallTip(tempPoint.x, tempPoint.y); //添加上一步落子提示
                    setArrowTip(pCol, pRow); //添加箭头提示
                    //白棋成型了
                    if (checkSymmetryShape(false)) {
                        changeState(ActionState.REMOVE_SHAPED_WHITE);//切换到白棋快捷提子状态
//                        int size = symmetryPieces.size();
//                        pieces.removeAll(symmetryPieces); //批量提子
//                        int score = size - 5; //计算得分
//                        whiteScore += score; //加分
//                if (whiteScore >= maxScore) {
//                    changeState(ActionState.WHITE_WIN); //白棋获胜
//                }
//                else {
//                        changeState(ActionState.WAIT_FALL_BLACK);
                    }
                    //白棋没成型
                    else {
                        changeState(ActionState.WAIT_FALL_BLACK);//自动交换黑棋行棋
                    }
                }
                //移动到原位置
                else {
                    //iGameUI.toast("不能移动到这个位置"); //提示用户不能这么做
                    setFallTip(tempPoint.x, tempPoint.y); //还原聚焦提示
                }
            }
            //移动的位置有棋
            else {
                //iGameUI.toast("不能移动到这个位置"); //提示用户不能这么做
                setFallTip(tempPoint.x, tempPoint.y); //还原落子提示
            }
        }
        //等待黑方挤走白棋的位置
        else if (checkState(ActionState.PUSH_AWAY_WHITE)) {
            //挤走位置相邻
            return;
//            if (Math.abs(tempPoint.x - pCol) < 2 && Math.abs(tempPoint.y - pRow) < 2) {
//                //放到空白位置
//                if (chessInfo == null) {
//                    fallPiece(false, pCol, pRow); //把白棋挤到这个位置
//                    setFallTip(tempPoint.x, tempPoint.y); //添加上一步的落子提示
//                    setArrowTip(pCol, pRow); //添加箭头提示
//                    //判断黑棋成型了
//                    if (checkSymmetryShape(true)) {
//                        changeState(ActionState.REMOVE_SHAPED_BLACK);//切换到黑棋快捷提子状态
//                    }
//                    //黑棋没成型
//                    else {
//                        changeState(ActionState.WAIT_FALL_WHITE);//自动交换白棋行棋
//                    }
//                }
//                //移动的位置有棋
//                else {
//                    //iGameUI.toast("只能挤到无棋的位置"); //提示用户不能这么做
//                    setFallTip(tempPoint.x, tempPoint.y); //还原落子提示
//                }
//            }
//            //挤走的位置不相邻
//            else {
//                //iGameUI.toast("只能挤到相邻一圈的位置"); //提示用户不能这么做
//                setFallTip(tempPoint.x, tempPoint.y); //还原落子提示
//            }
        }
        //等待白方挤走黑棋的位置
        else if (checkState(ActionState.PUSH_AWAY_BLACK)) {
            return;
            //挤走位置相邻
//            if (Math.abs(tempPoint.x - pCol) < 2 && Math.abs(tempPoint.y - pRow) < 2) {
//                //放到空白位置
//                if (chessInfo == null) {
//                    fallPiece(true, pCol, pRow); //把黑棋挤到这个位置
//                    setFallTip(tempPoint.x, tempPoint.y); //添加上一步的落子提示
//                    setArrowTip(pCol, pRow); //添加箭头提示
//                    //判断白棋成型了
//                    if (checkSymmetryShape(false)) {
//                        changeState(ActionState.REMOVE_SHAPED_WHITE);//切换到白棋快捷提子状态
//                    }
//                    //黑棋没成型
//                    else {
//                        changeState(ActionState.WAIT_FALL_BLACK);//自动交换黑棋行棋
//                    }
//                }
//                //移动的位置有棋
//                else {
//                    //iGameUI.toast("只能挤到无棋的位置"); //提示用户不能这么做
//                }
//            }
//            //挤走的位置不相邻
//            else {
//                //iGameUI.toast("只能挤到相邻一圈的位置"); //提示用户不能这么做
//            }
        }
        //等待提走成型的黑棋
        else if (checkState(ActionState.REMOVE_SHAPED_BLACK)) {
            if (symmetryPieces.contains(chessInfo)) {
                int size = symmetryPieces.size();
                pieces.removeAll(symmetryPieces); //批量提子
                int score = size - 5; //计算得分
                blackScore += score; //加分
//                if (blackScore >= maxScore) {
//                    changeState(ActionState.BLACK_WIN); //黑棋获胜
//                }
//                else {
                changeState(ActionState.WAIT_FALL_WHITE); //提子后走白棋
//                }
            } else {
                //iGameUI.toast("请点击成型的区域快捷提子"); //提示用户正确的操作
            }
        }
        //等待提走成型的白棋
        else if (checkState(ActionState.REMOVE_SHAPED_WHITE)) {
            if (symmetryPieces.contains(chessInfo)) {
                int size = symmetryPieces.size();
                pieces.removeAll(symmetryPieces); //批量提子
                int score = size - 5; //计算得分
                whiteScore += score; //加分
//                if (whiteScore >= maxScore) {
//                    changeState(ActionState.WHITE_WIN); //白棋获胜
//                }
//                else {
                changeState(ActionState.WAIT_FALL_BLACK); //提子后走黑棋
//                }
            } else {
                //iGameUI.toast("请点击成型的区域快捷提子"); //提示用户正确的操作
            }
        }
    }

    //判断该位置相邻格子是否存在空格
    private boolean checkHasQi(int pCol, int pRow) {
        int maxRow = curGrids.length - 1;
        int maxCol = curGrids[0].length - 1;
        boolean hasQi = false;
        if (pRow > 0 && pCol > 0 && curGrids[pRow - 1][pCol - 1] == 0) {
            hasQi = true;
        }
        if (pRow > 0 && curGrids[pRow - 1][pCol] == 0) {
            hasQi = true;
        }
        if (pRow > 0 && pCol < maxCol && curGrids[pRow - 1][pCol + 1] == 0) {
            hasQi = true;
        }
        if (pCol > 0 && curGrids[pRow][pCol - 1] == 0) {
            hasQi = true;
        }
        if (pCol < maxCol && curGrids[pRow][pCol + 1] == 0) {
            hasQi = true;
        }
        if (pRow < maxRow && pCol > 0 && curGrids[pRow + 1][pCol - 1] == 0) {
            hasQi = true;
        }
        if (pRow < maxRow && curGrids[pRow + 1][pCol] == 0) {
            hasQi = true;
        }
        if (pRow < maxRow && pCol < maxCol && curGrids[pRow + 1][pCol + 1] == 0) {
            hasQi = true;
        }
        return hasQi;
    }

    //根据坐标点获取棋子
    private ChessInfo getChessByPoint(int pCol, int pRow) {
        for (ChessInfo piece : pieces) {
            if (piece.col == pCol && piece.row == pRow) {
                return piece;
            }
        }
        return null;
    }

    //记录落子位置
    private void setTempPoint(int pCol, int pRow) {
        tempPoint = new Point(pCol, pRow);
    }

    //判断当前状态
    private boolean checkState(ActionState state) {
        return actionState == state;
    }

    //转换状态
    private void changeState(ActionState state) {//114514
        ActionState preActionState = actionState;
        actionState = state;
        if (actionState == ActionState.WAIT_FALL_BLACK || actionState == ActionState.WAIT_FALL_WHITE) {
            //if (!canPlaceRandomFour()){
            //    checkWin();
            //}else {
            int validNum = 0;
            for (int i = 0; i < curGrids.length; i++) {
                for (int j = 0; j < curGrids[0].length; j++) {
                    if (isKingPosition(curGrids, i, j, cur)) {
//                        signIds.add(getIndex(i,j));
//                        signList.add(new TextSign(getIndex(i, j), "·", "#FF000000"));
                        validNum++;
                    }
                }
            }
            if (preActionState == ActionState.REMOVE_SHAPED_BLACK || preActionState == ActionState.REMOVE_SHAPED_WHITE) {
                if (cur == 1) {
                    blackWarnning = 0;
                } else if (cur == 2){
                    whtieWarnning = 0;
                }
            } else if (validNum < 15) {
                if ((cur == 1 ? blackWarnning : whtieWarnning) == 3) {
                    hadEnd = true;
                } else {
                    if (cur == 1) {
                        blackWarnning++;
                    } else if (cur == 2){
                        whtieWarnning++;
                    }
                }
            } else {
                if (cur == 1) {
                    blackWarnning = 0;
                } else if (cur == 2){
                    whtieWarnning = 0;
                }
            }
            pushChess();
            if (hadEnd) {
                checkWin();
                //hadEnd = false;
                return;
            }
            //}
        }
        gameTip = state.tip;
        refreshUI();
    }

    private void checkWin() {
        if (blackScore > BOTH_WIN && whiteScore > BOTH_WIN) {
            changeState(ActionState.BLACK_AND_WHITE_WIN);
        } else if (blackScore > BOTH_WIN || (blackScore > BOTH_FAIL && blackScore > whiteScore)) {
            changeState(ActionState.BLACK_WIN);
        } else if (whiteScore > BOTH_WIN || whiteScore > BOTH_FAIL && whiteScore > blackScore) {
            changeState(ActionState.WHITE_WIN);
        } else if (blackScore > BOTH_FAIL) {
            changeState(ActionState.DRAW_GAME);
        } else {
            changeState(ActionState.ALL_LOSE);
        }
    }

    private void pushChess() {
        curGrids = GridsUtils.copyGrids(originGrids);
        List<Integer> indexes = new ArrayList<Integer>();
        //绘制棋子
        if (pieces != null && pieces.size() > 0) {
            for (ChessInfo piece : pieces) {
                if (step == 0) {
                    curGrids[piece.row][piece.col] = 1;
                }
                curGrids[piece.row][piece.col] = piece.isBlack ? 1 : 2;
            }
        }
        // 随机生成4个位置并放置棋子
//        int blackCount = GridsUtils.getDataCount(curGrids, 1);
//        int whiteCount = GridsUtils.getDataCount(curGrids, 2);
//        if (cur == 1){
//            if (whiteCount<16){
//                autoPutNum = 4;
//            }else if (whiteCount<31){
//                autoPutNum = 3;
//            }else {
//                autoPutNum = 2;
//            }
//        }else {
//            if (blackCount<16){
//                autoPutNum = 4;
//            }else if (blackCount<31){
//                autoPutNum = 3;
//            }else{
//                autoPutNum = 2;
//            }
//        }
        int[] isRandom = new int[autoPutNum];
        Arrays.fill(isRandom, -1);
        for (int i = 0; i < autoPutNum; i++) {
            int randomNumber;
            if (isRandom[i] != -1) {
                Random random = new Random();
                randomNumber = random.nextInt(weight1+1);
                isRandom[i] = randomNumber;
            } else {
                randomNumber = isRandom[i];
            }
            int x = (int) (Math.random() * curGrids.length); // 随机生成行坐标
            int y = (int) (Math.random() * curGrids[0].length); // 随机生成列坐标
            if (checkIsValid()) {
                if (randomNumber != 0) {

                    // 检查该位置是否合法
                    if (isKingPosition(curGrids, x, y, cur == 1 ? 2 : 1)) {
                        if (cur == 1) {
                            fallPiece(false, y, x);
                            curGrids[x][y] = 2;
                        } else {
                            fallPiece(true, y, x);
                            curGrids[x][y] = 1;
                        }
                        indexes.add(getIndex(x, y));
                    } else {
                        i--; // 如果位置不合法，则重新生成位置
                    }
                } else {
                    if (curGrids[x][y] != 0) {
                        i--;
                    } else if (!isKingPosition(curGrids, x, y, cur == 1 ? 2 : 1)) {
                        if (cur == 1) {
                            fallPiece(false, y, x);
                            curGrids[x][y] = 2;
                        } else {
                            fallPiece(true, y, x);
                            curGrids[x][y] = 1;
                        }
                        indexes.add(getIndex(x, y));
                    } else {
                        i--;
                    }
                }
            } else {
//                    hadEnd = true;
//                    break;
                if (curGrids[x][y] != 0) {
                    i--;
                } else if (!isKingPosition(curGrids, x, y, cur == 1 ? 2 : 1)) {
                    if (cur == 1) {
                        fallPiece(false, y, x);
                        curGrids[x][y] = 2;
                    } else {
                        fallPiece(true, y, x);
                        curGrids[x][y] = 1;
                    }
                    indexes.add(getIndex(x, y));
                } else {
                    i--;
                }
            }
        }
        fallTipByAuto = new AroundSign(indexes, "#00000000", ColorCost.NEW_PUT_POINT, 1.2f);
        //noticeAllRefreshGameInfo();
        //signList
    }

    private boolean checkIsValid() {

        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[0].length; j++) {
                if (isKingPosition(curGrids, i, j, cur == 1 ? 2 : 1)) {
                    return true;
                }
            }
        }
        return false;
    }


    private int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};

    // 检查给定位置是否合法
    private boolean isKingPosition(int[][] curGrids, int row, int col, int thisCur) {

        if (curGrids[row][col] != 0) return false;
        for (int[] move : kingMoves) {
            int nextRow = row + move[0];
            int nextCol = col + move[1];
            if (nextRow < curGrids.length && nextCol < curGrids[0].length && nextRow >= 0 && nextCol >= 0)
                if (curGrids[nextRow][nextCol] == thisCur) {
                    return false;
//                    break;
                }
        }
        return true;
    }
    private boolean isValidPosition(int[][] curGrids, int x, int y, int thisCur) {

        if (curGrids[x][y] != 0) return false;
//        if (!isThisCur){
//            thisCur = cur == 1 ? 2 : 1;
//        }else {
//            thisCur = cur;
//        }
        // 检查上方
        if ((x > 0 && curGrids[x - 1][y] == thisCur) || (x > 1 && curGrids[x - 2][y] == thisCur)) return false;

        // 检查下方
        if ((x < curGrids.length - 1 && curGrids[x + 1][y] == thisCur) || (x < curGrids.length - 2 && curGrids[x + 2][y] == thisCur))
            return false;

        // 检查左方
        if ((y > 0 && curGrids[x][y - 1] == thisCur) || (y > 1 && curGrids[x][y - 2] == thisCur)) return false;

        // 检查右方
        if ((y < curGrids[0].length - 1 && curGrids[x][y + 1] == thisCur) || (y < curGrids[0].length - 2 && curGrids[x][y + 2] == thisCur))
            return false;

        // 检查左上方
        if (x > 0 && y > 0 && curGrids[x - 1][y - 1] == thisCur) return false;

        // 检查右上方
        if (x > 0 && y < curGrids[0].length - 1 && curGrids[x - 1][y + 1] == thisCur) return false;

        // 检查左下方
        if (x < curGrids.length - 1 && y > 0 && curGrids[x + 1][y - 1] == thisCur) return false;

        // 检查右下方
        if (x < curGrids.length - 1 && y < curGrids[0].length - 1 && curGrids[x + 1][y + 1] == thisCur) return false;

        return true; // 位置合法
    }

    private void refreshUI() {
        if (checkState(ActionState.WAIT_FALL_BLACK)) {
            stepAdd();
            noticeBlackMove();
        } else if (checkState(ActionState.WAIT_FALL_WHITE)) {
            stepAdd();
            noticeWhiteMove();
        } else if (checkState(ActionState.THEN_MOVE_BLACK)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.THEN_MOVE_WHITE)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.PUSH_AWAY_WHITE)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.PUSH_AWAY_BLACK)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.REMOVE_SHAPED_BLACK)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.REMOVE_SHAPED_WHITE)) {
            noticeAllRefreshGameInfo();
        } else if (checkState(ActionState.BLACK_AND_WHITE_WIN)) {
            stepAdd();

            doOver(WinMode.BOTH_DRAW, player_black.getNickName() + "执黑棋与" + player_white.getNickName() + "执白棋共同获胜");
        } else if (checkState(ActionState.ALL_LOSE)) {
            stepAdd();
            doOver(WinMode.BOTH_DRAW, player_black.getNickName() + "执黑棋与" + player_white.getNickName() + "执白棋共同失败");
        } else if (checkState(ActionState.DRAW_GAME)) {
            stepAdd();
            doOver(WinMode.BOTH_DRAW, player_black.getNickName() + "-黑棋战平" + player_white.getNickName() + "-白棋");
        } else if (checkState(ActionState.BLACK_WIN)) {
            stepAdd();
            doOver(WinMode.BLACK_WIN, player_black.getNickName() + "执黑棋战胜" + player_white.getNickName());
        } else if (checkState(ActionState.WHITE_WIN)) {
            stepAdd();
            doOver(WinMode.WHITE_WIN, player_white.getNickName() + "执白棋战胜" + player_black.getNickName());
        }
        fallTipByAuto = null;
    }

    //在棋盘上指定坐标上落下新棋子
    private void fallPiece(boolean isBlack, int pCol, int pRow) {
        ChessInfo p = new ChessInfo(isBlack, pCol, pRow); //创建新的黑棋
        pieces.add(p); //落下黑子
    }

    //在指定坐标上添加落子提示
    private void setFallTip(int pCol, int pRow) {
        fallTip = new GroundSign(getIndex(pRow, pCol), "#00000000", ColorCost.NEW_PUT_POINT, 1.0f, 0, 0);
    }

    //指定坐标设定箭头提示
    private void setArrowTip(int pCol, int pRow) {
        arrowTip = new LineSign(getIndex(tempPoint.y, tempPoint.x), getIndex(pRow, pCol), ColorCost.MOVE_ARROW, 1);
    }

    //检查是否形成了对称图形
    private boolean checkSymmetryShape(boolean isBlackChess) {
        boolean isSymmetryShaped = false;
        symmetryPieces.clear();
        List<ChessInfo> iChess = new ArrayList<>(pieces);
        iChess.removeIf(chessInfo -> chessInfo.isBlack != isBlackChess); //保留同色棋子集合
        Map<ChessInfo, Set<ChessInfo>> adjacentGroup = new HashMap<>(); //相邻棋子组成的组
        for (ChessInfo key : iChess) { //每个棋子都建立一个自己的组
            Set<ChessInfo> set = new HashSet<>();
            set.add(key);
            adjacentGroup.put(key, set);
        }
        int size = iChess.size();
        for (int i = 0; i < size; i++) { //第一次遍历所有相邻棋子建立相邻关系
            for (int j = i + 1; j < size; j++) { //保证任意两个棋子只判断一次
                ChessInfo a = iChess.get(i);
                ChessInfo b = iChess.get(j);
                if (isAdjacent(a, b)) {
                    adjacentGroup.get(a).add(b);
                    adjacentGroup.get(b).add(a);
                }
            }
        }
        //printAdjacentGroup("第一次建立关系", adjacentGroup);
        Map<ChessInfo, Set<ChessInfo>> blockGroup = new HashMap<>();
        for (int i = 0; i < size; i++) { //第二次遍历所有邻组合并
            ChessInfo a = iChess.get(i);//因为adjacentGroup是map没有顺序索引所以借助iChess集合来遍历
            Set<ChessInfo> aSet = adjacentGroup.get(a);
            for (ChessInfo blockKey : blockGroup.keySet()) {  //判断这一组是否和已经有的块有交集，保证块不重复
                Set<ChessInfo> blockSet = blockGroup.get(blockKey);
                if (isIntersection(aSet, blockSet)) { //如果有的话
                    a = blockKey;   //就还是用最早的键来判断
                    blockSet.addAll(aSet); //且把这一组的所有棋子添加到块中
                    aSet = blockSet; //且用最全的集合来判断
                }
            }
            for (int j = i + 1; j < size; j++) {
                ChessInfo b = iChess.get(j);
                Set<ChessInfo> bSet = adjacentGroup.get(b);
                if (isIntersection(aSet, bSet)) {
                    aSet.addAll(bSet); //判断过有交集的都要收集起来以免后面的漏判
                    blockGroup.put(a, aSet); //这里的a始终是最早的块键
                }
            }
        }
        //printAdjacentGroup("合并邻组后", blockGroup);
        Map<ChessInfo, Set<ChessInfo>> singleGroup = new HashMap<>();//此时可能出现来自不同相邻关系组成的相同集合的组，将其净化掉
        for (ChessInfo blockKey : blockGroup.keySet()) {
            Set<ChessInfo> blockSet = blockGroup.get(blockKey);
            boolean isSetEqual = false;
            for (ChessInfo singleKey : singleGroup.keySet()) {
                Set<ChessInfo> singleSet = singleGroup.get(singleKey);
                isSetEqual = isSetEqual(blockSet, singleSet);
                if (isSetEqual) {  //一旦存在相同就不要继续比较了，这组不加到singleGroup中
                    break;
                }
            }
            if (!isSetEqual) {
                singleGroup.put(blockKey, blockSet);
            }
        }
        //printAdjacentGroup("去除相同组后", singleGroup);
        for (ChessInfo key : singleGroup.keySet()) {
            Set<ChessInfo> singleSet = singleGroup.get(key);
            if (singleSet.size() >= 6) { //棋子数量小于6的块都不去考虑了
                int minCol = -1, minRow = -1, maxCol = -1, maxRow = -1;
                for (ChessInfo chessInfo : singleSet) { //获取区间范围
                    if (minCol == -1) { //注意第一次赋予初值
                        minCol = chessInfo.col;
                        maxCol = chessInfo.col;
                        minRow = chessInfo.row;
                        maxRow = chessInfo.row;
                    }
                    if (chessInfo.col > maxCol) {
                        maxCol = chessInfo.col;
                    }
                    if (chessInfo.col < minCol) {
                        minCol = chessInfo.col;
                    }
                    if (chessInfo.row > maxRow) {
                        maxRow = chessInfo.row;
                    }
                    if (chessInfo.row < minRow) {
                        minRow = chessInfo.row;
                    }
                }
                float midCol = (minCol + maxCol) / 2f; //获取中心点横坐标，用于后续计算
                float midRow = (minRow + maxRow) / 2f; //获取中心点纵坐标，用于后续计算
                if (checkHorizontalSymmetry(singleSet, midCol)) {
                    isSymmetryShaped = true;
                    symmetryPieces.addAll(singleSet);
                } else if (checkVerticalSymmetry(singleSet, midRow)) {
                    isSymmetryShaped = true;
                    symmetryPieces.addAll(singleSet);
                } else if (checkPositiveSymmetry(singleSet, midCol, midRow)) {
                    isSymmetryShaped = true;
                    symmetryPieces.addAll(singleSet);
                } else if (checkNegativeSymmetry(singleSet, midCol, midRow)) {
                    isSymmetryShaped = true;
                    symmetryPieces.addAll(singleSet);
                }
            }
        }
        return isSymmetryShaped;
    }

    //判断是否水平对称无斜率（一条竖线两边全等）
    private boolean checkHorizontalSymmetry(Set<ChessInfo> blockChessSet, float midCol) {
        Set<Point> blockSet = new HashSet<>();
        for (ChessInfo chessInfo : blockChessSet) {
            blockSet.add(new Point(chessInfo.col, chessInfo.row));
        }
        Set<Point> left = new HashSet<>();
        Set<Point> right = new HashSet<>();
        for (Point chessInfo : blockSet) {
            if (chessInfo.x < midCol) {
                left.add(chessInfo);
                float diff = midCol - chessInfo.x; //计算要翻转的值
                chessInfo.x = (int) (midCol + diff); //翻转坐标
            } else if (chessInfo.x > midCol) {
                right.add(chessInfo);
            }
        }
        boolean isFlag = isSameCoordinate(left, right); //判断两组棋子横纵坐标是否全等
        return isFlag;
    }

    //判断是否垂直对称（一条横线两边全等）
    private boolean checkVerticalSymmetry(Set<ChessInfo> blockChessSet, float midRow) {
        Set<Point> blockSet = new HashSet<>();
        for (ChessInfo chessInfo : blockChessSet) {
            blockSet.add(new Point(chessInfo.col, chessInfo.row));
        }
        Set<Point> top = new HashSet<>();
        Set<Point> bottom = new HashSet<>();
        for (Point chessInfo : blockSet) {
            if (chessInfo.y < midRow) {
                top.add(chessInfo);
                float diff = midRow - chessInfo.y; //计算要翻转的值
                chessInfo.y = (int) (midRow + diff); //翻转坐标
            } else if (chessInfo.y > midRow) {
                bottom.add(chessInfo);
            }
        }
        boolean isFlag = isSameCoordinate(top, bottom);
        return isFlag;
    }

    //判断是否以45°的斜线对称
    private boolean checkPositiveSymmetry(Set<ChessInfo> blockChessSet, float midCol, float midRow) {
        Set<Point> blockSet = new HashSet<>();
        for (ChessInfo chessInfo : blockChessSet) {
            blockSet.add(new Point(chessInfo.col, chessInfo.row));
        }
        Set<Point> leftTop = new HashSet<>();
        Set<Point> rightBottom = new HashSet<>();
        float split = midCol + midRow;
        for (Point chessInfo : blockSet) {
            if (chessInfo.y + chessInfo.x < split) {
                leftTop.add(chessInfo);
                //先求两条直线的交点
                float b = midCol + midRow; //根据公式y = ax + b;a=-1; 求对称线的公式需要的参数
                float h = chessInfo.y - chessInfo.x; //求对齐线的公式需要的参数
                float jX = (b - h) / 2; //求出垂线交点x
                float jY = (b + h) / 2;//求出垂线交点y
                float diffX = jX - chessInfo.x;
                chessInfo.x = (int) (jX + diffX);
                float diffY = jY - chessInfo.y;
                chessInfo.y = (int) (jY + diffY);
            } else if (chessInfo.y + chessInfo.x > split) {
                rightBottom.add(chessInfo);
            }
        }
        boolean isFlag = isSameCoordinate(leftTop, rightBottom);
        return isFlag;
    }

    //判断是否以-45°的斜线对称
    private boolean checkNegativeSymmetry(Set<ChessInfo> blockChessSet, float midCol, float midRow) {
        Set<Point> blockSet = new HashSet<>();
        for (ChessInfo chessInfo : blockChessSet) {
            blockSet.add(new Point(chessInfo.col, chessInfo.row));
        }
        Set<Point> left = new HashSet<>();
        Set<Point> right = new HashSet<>();
        for (Point chessInfo : blockSet) {  //先全部水平翻转，这样midCol和midRow不会变，而变成可以以正45°斜线对称了
            if (chessInfo.x < midCol) {
                left.add(chessInfo);
                float diff = midCol - chessInfo.x;
                chessInfo.x = (int) (midCol + diff);
            } else if (chessInfo.x > midCol) {
                right.add(chessInfo);
                float diff = chessInfo.x - midCol;
                chessInfo.x = (int) (midCol - diff); //还原改变
            }
        }
        Set<Point> leftTop = new HashSet<>();
        Set<Point> rightBottom = new HashSet<>();
        float split = midCol + midRow;
        for (Point chessInfo : blockSet) {
            if (chessInfo.y + chessInfo.x < split) {
                leftTop.add(chessInfo);
                float b = midCol + midRow; //根据公式y = ax + b;a=-1; 求对称线的公式需要的参数
                float h = chessInfo.y - chessInfo.x; //求对齐线的公式需要的参数
                float jX = (b - h) / 2; //求出垂线交点x
                float jY = (b + h) / 2;//求出垂线交点y
                float diffX = jX - chessInfo.x;
                chessInfo.x = (int) (jX + diffX);
                float diffY = jY - chessInfo.y;
                chessInfo.y = (int) (jY + diffY);
            } else if (chessInfo.y + chessInfo.x > split) {
                rightBottom.add(chessInfo);
            }
        }
        boolean isFlag = isSameCoordinate(leftTop, rightBottom);
        return isFlag;
    }

    //打印邻组，邻组是我算法里的一个中间概念
    private void printAdjacentGroup(String title, Map<?, Set<ChessInfo>> adjacentGroup) {
        int row = curGrids.length;
        //System.out.println(title + "有" + adjacentGroup.size() + "组");
        for (Object key : adjacentGroup.keySet()) {
            ChessInfo keyChess = (ChessInfo) key;
            String colStr = String.valueOf((char) ('A' + keyChess.col));
            String rowStr = String.valueOf(row - keyChess.row);
            //System.out.print(colStr + rowStr + "组 ");
            for (ChessInfo chessInfo : adjacentGroup.get(key)) {
                String colStr2 = String.valueOf((char) ('A' + chessInfo.col));
                String rowStr2 = String.valueOf(row - chessInfo.row);
                //System.out.print(colStr2 + rowStr2 + "；");
            }
            //System.out.println("。");
        }
    }

    //判断两个棋子是否相邻(直向和斜向相邻都算,位置相同不算)
    private boolean isAdjacent(ChessInfo a, ChessInfo b) {
        if (a.col == b.col && a.row == b.row) {
            return false;
        } else {
            return Math.abs(a.col - b.col) <= 1 && Math.abs(a.row - b.row) <= 1;
        }
    }

    //判断两组棋子横纵坐标是否全等
    private boolean isSameCoordinate(Set<Point> aSet, Set<Point> bSet) {
        if (aSet.size() != bSet.size()) {
            return false;
        } else {
            for (Point chessInfo : aSet) {
                boolean same = false;
                for (Point info : bSet) {
                    if (info.y == chessInfo.y && info.x == chessInfo.x) {
                        same = true;
                        break;
                    }
                }
                if (!same) {
                    return false;
                }
            }
        }
        return true;
    }

    //判断两个邻组是否有交集（只要有一个棋子双方都存在就算有交集）
    private boolean isIntersection(Set<ChessInfo> aSet, Set<ChessInfo> bSet) {
        Set<ChessInfo> resSet = new HashSet<>(aSet);
        resSet.retainAll(bSet); //++这个可能无法判断出来顺序不一致的情况
        return resSet.size() > 0;
    }

    //判断两个集合是否相同
    public boolean isSetEqual(Set<ChessInfo> aSet, Set<ChessInfo> bSet) {
        int a = aSet.size();
        int b = bSet.size();
        if (a == b) {
            Set<ChessInfo> resSet = new HashSet<>();
            resSet.addAll(aSet);
            resSet.addAll(bSet);
            int c = resSet.size();
            return c == a;
        } else {
            return false;
        }
    }

    private static class ChessInfo {

        public boolean isBlack;
        public int col;
        public int row;

        public ChessInfo(boolean isBlack, int col, int row) {
            this.isBlack = isBlack;
            this.col = col;
            this.row = row;
        }
    }

    private enum ActionState {
        /**
         * 等待黑棋落子
         */
        WAIT_FALL_BLACK("等待黑棋落子..."),
        /**
         * 等待白棋落子
         */
        WAIT_FALL_WHITE("等待白棋落子..."),

        /**
         * 黑棋落黑棋后移动
         */
        THEN_MOVE_BLACK("选择黑棋移动的位置..."),
        /**
         * 白棋落白棋后移动
         */
        THEN_MOVE_WHITE("选择白棋移动的位置..."),

        /**
         * 选择被黑棋挤走的白棋的位置
         */
        PUSH_AWAY_WHITE("选择白棋被挤到的位置..."),
        /**
         * 选择被白棋挤走的黑棋的位置
         */
        PUSH_AWAY_BLACK("选择黑棋被挤到的位置..."),

        /**
         * 一键提走成型的黑棋（提子后算分）
         */
        REMOVE_SHAPED_BLACK("点击黑棋成型的区域快捷提子..."),
        /**
         * 一键提走成型的白棋（提子后算分）
         */
        REMOVE_SHAPED_WHITE("点击白棋成型的区域快捷提子..."),

        /**
         * 对弈结束，黑方获胜，棋盘不再接受事件
         */
        BLACK_WIN("恭喜黑棋获胜！"),
        /**
         * 对弈结束，黑白方获胜，棋盘不再接受事件
         */
        BLACK_AND_WHITE_WIN("恭喜黑棋与白棋都获胜！"),
        /**
         * 对弈结束，白方获胜，棋盘不再接受事件
         */
        WHITE_WIN("恭喜白棋获胜！"),
        /**
         * 对弈结束，白方获胜，棋盘不再接受事件
         */
        ALL_LOSE("黑白双方都落败！"),

        DRAW_GAME("黑白和棋！");
        /**
         * 该状态对应的操作提示
         */
        public final String tip;

        ActionState(String tip) {
            this.tip = tip;
        }
    }

}
